package com.raven.play.datalink.jdbc;

import com.typesafe.config.Config;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import javax.sql.DataSource;

public class JdbcDataSourceFactory {

    public static DataSource create(Config config) {
        String connectionPoolType = config.getString("connectionPool");

        switch (connectionPoolType) {
            case "HikariCP":
                if (!config.hasPath("properties")) throw new IllegalArgumentException("Config[properties] not exists");
                return createHikariDataSource(config.getConfig("properties"));
            default:
                throw new UnsupportedOperationException("Unknown connection pool type: " + connectionPoolType);
        }

    }

    private static DataSource createHikariDataSource(Config config) {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl(getString(config, "url"));
        hikariConfig.setUsername(getString(config, "username"));
        hikariConfig.setPassword(getString(config, "password"));
        hikariConfig.setDriverClassName(getString(config, "driver"));

        hikariConfig.setConnectionTimeout(getLong(config, "connectionTimeout", 30000L));
        hikariConfig.setIdleTimeout(getLong(config, "idleTimeout", 60000L));
        hikariConfig.setMaxLifetime(getLong(config, "maxLifetime", 600000L));
        hikariConfig.setMaximumPoolSize(getInt(config, "maximumPoolSize", 5));
        hikariConfig.setMinimumIdle(getInt(config, "minimumIdle", 0));
        hikariConfig.setValidationTimeout(getInt(config, "validationTimeout", 5000));
        hikariConfig.setLeakDetectionThreshold(getInt(config, "leakDetectionThreshold", 0));

        hikariConfig.setConnectionTestQuery(getString(config, "connectionTestQuery"));
        hikariConfig.setPoolName(getString(config, "poolName"));

        hikariConfig.setAutoCommit(false); // 关闭自动保存

        return new HikariDataSource(hikariConfig);
    }

    private static Long getLong(Config config, String name) {
        return getLong(config, name);
    }

    private static Long getLong(Config config, String name, Long defaultValue) {
        if (config.hasPath(name)) {
            return config.getLong(name);
        } else {
            return defaultValue;
        }
    }

    private static Integer getInt(Config config, String name) {
        return getInt(config, name, null);
    }

    private static Integer getInt(Config config, String name, Integer defaultValue) {
        if (config.hasPath(name)) {
            return config.getInt(name);
        } else {
            return defaultValue;
        }
    }

    private static String getString(Config config, String name) {
        return getString(config, name, null);
    }

    private static String getString(Config config, String name, String defaultValue) {
        if (config.hasPath(name)) {
            return config.getString(name);
        } else {
            return defaultValue;
        }
    }

}
